using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Xml;
using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using System.IO;
using Microsoft.VisualStudio.CommandBars;

namespace WindowsPhoneToolbox.Util
{
    public static class Common
    {
        public static string GetStatus()
        {
            switch (WindowsPhoneToolboxPackage.DbgmodeNew)
            {
                case DBGMODE.DBGMODE_Design:
                    {
                        if (WPhoneDevice.IsConnected)
                        {
                            return Resources.Connected;
                        }
                        return Resources.Disconnected;
                    }
                case DBGMODE.DBGMODE_Break:
                    {
                        if (WPhoneDevice.IsConnected)
                        {
                            return Resources.Connected + " " + Resources.DebugBreak;
                        }
                        return Resources.Disconnected + " " + Resources.DebugBreak;
                    }
                case DBGMODE.DBGMODE_Enc:
                case DBGMODE.DBGMODE_EncMask:
                    {
                        if (WPhoneDevice.IsConnected)
                        {
                            return Resources.Connected + " " + Resources.DebugEnc;
                        }
                        return Resources.Disconnected + " " + Resources.DebugEnc;
                    }
                case DBGMODE.DBGMODE_Run:
                    {
                        if (WPhoneDevice.IsConnected)
                        {
                            return Resources.Connected + " " + Resources.DebugRun;
                        }
                        return Resources.Disconnected + " " + Resources.DebugRun;
                    }
            }
            return Resources.Error;
        }

        public static string XmlEscape(string unescaped)
        {
            var doc = new XmlDocument();
            var node = doc.CreateElement("root");
            node.InnerText = unescaped;
            return node.InnerXml;
        }

        public static string XmlUnescape(string escaped)
        {
            var doc = new XmlDocument();
            var node = doc.CreateElement("root");
            node.InnerXml = escaped;
            return node.InnerText;
        }

        public static bool XmlBoolConvert(string value, bool defaultvalue,bool optional)
        {
            if (value.ToLower() == "false" || value == "0") return false;
            if (value.ToLower() == "true" || value == "1") return true;
            if (string.IsNullOrEmpty(value) && optional) return defaultvalue;
            throw new InvalidCastException("Invalid cast to bool value : " + value);
        }

        public static bool XmlBoolConvert(string value, bool defaultvalue)
        {
            return XmlBoolConvert(value, defaultvalue, false);
        }

        public static string XmlBitPixelConvert(string value)
        {
            return String.IsNullOrEmpty(value) ? "16" : value;
        }

        public static string FormatBytes(long bytes)
        {
            const int scale = 1024;
            var orders = new[] { "Gb", "Mb", "Kb", "Bytes" };
            var max = (long)Math.Pow(scale, orders.Length - 1);

            foreach (string order in orders)
            {
                if (bytes > max)
                    return String.Format("{0:##.##} {1}", Decimal.Divide(bytes, max), order);

                max /= scale;
            }
            return "0 Bytes";
        }

        public static string GetTargetDevice(DTE2 dte)
        {
            var result = string.Empty;
            foreach (CommandBar commandBar in (_CommandBars)dte.CommandBars)
            {
                foreach (var obj in commandBar.Controls)
                {
                    var commandBarComboBox = obj as CommandBarComboBox;
                    if (commandBarComboBox != null && commandBarComboBox.accName[Missing.Value] == "Target Deployment Device")
                    {
                        result =  GetCurrentWpComboText();
                        break;
                    }
                }
            }
            return result;
        }

        private static string GetCurrentWpComboText()
        {
            var oleCommandTarget = (Microsoft.VisualStudio.OLE.Interop.IOleCommandTarget)Package.GetGlobalService(typeof(SUIHostCommandDispatcher));
            if (oleCommandTarget != null)
            {
                var pguidCmdGroup = Guid.Parse("{04151D39-35B6-4E53-BEEE-48DF3BB8CFE5}");
                const uint nCmdId = 257U;
                var num = Marshal.AllocCoTaskMem(16);
                if (num != IntPtr.Zero)
                {
                    try
                    {
                        Marshal.WriteInt16(num, 8);
                        if (oleCommandTarget.Exec(ref pguidCmdGroup, nCmdId, 0U, IntPtr.Zero, num) == 0)
                            return (string)Marshal.GetObjectForNativeVariant(num);
                    }
                    finally
                    {
                        Marshal.FreeCoTaskMem(num);
                    }
                }
            }
            return string.Empty;
        }

        public static ProjectItem GetManifestWp(ProjectItem item)
        {
            if (item.Name.ToLower().Contains(DefaultnameManifestWp().ToLower()))
            {
                return item;
            }
            if (item.ProjectItems == null)
            {
                return null;
            }
            var subitems = item.ProjectItems.GetEnumerator();
            while (subitems.MoveNext())
            {
                var result = GetManifestWp((ProjectItem)subitems.Current);
                if (result != null)
                {
                    return  result;
                }
            }
            return null;
        }

        public static string GetPathFileManifest(Project project)
        {
            if (project.ProjectItems == null) return null;

            var subitems = project.ProjectItems.GetEnumerator();
            ProjectItem result = null;
            while (subitems.MoveNext())
            {
                result = GetManifestWp((ProjectItem)subitems.Current);
                if (result != null)
                {
                    break;
                }
            }
            return result != null ? result.Properties.Item("FullPath").Value.ToString() : null;
        }

        public static string GetPathFileManifest(ProjectItem item)
        {
            var result = GetManifestWp(item);
            return result != null ? result.Properties.Item("FullPath").Value.ToString() : null;
        }

        public static string DefaultnameManifestWp()
        {
            return "WMAppManifest.xml";
        }

        public static Project FindProjectByName(DTE2 dte, string name)
        {
            Project found = null;
            if (dte != null)
            {
                var enumprjs = dte.Solution.Projects.GetEnumerator();
                while (enumprjs.MoveNext())
                {
                    if (((Project)enumprjs.Current).Name == name)
                    {
                        found = (Project)enumprjs.Current;
                        break;
                    }
                }
            }
            return found;
        }

        public static bool AreAllValidNumericChars(string str)
        {
            return str.All(Char.IsNumber);
        }

        public static List<string> GetListFilesFromProject(Project project, string[] extensions)
        {
            var result = new List<string>();
            var enumprjs = project.ProjectItems.GetEnumerator();
            var directoryInfo = new FileInfo(project.FullName).Directory;
            var root = String.Empty;
            if (directoryInfo != null)
            {
                root = directoryInfo.FullName + "\\";
            }
            while (enumprjs.MoveNext())
            {
                try
                {
                    var fileextension = ((ProjectItem)enumprjs.Current).Properties.Item("Extension").Value.ToString().ToUpper();
                    if (extensions.Any(extfind => fileextension.ToUpper() == extfind.ToUpper()))
                    {
                        var localpath = ((ProjectItem)enumprjs.Current).Properties.Item("LocalPath").Value.ToString();
                        result.Add(localpath.Replace(root,""));
                    }
                }
                // ReSharper disable EmptyGeneralCatchClause
                catch 
                // ReSharper restore EmptyGeneralCatchClause
                {
                }
                if (((ProjectItem)enumprjs.Current).ProjectItems != null)
                {
                    result.AddRange(GetsubItemImages(root,extensions, ((ProjectItem)enumprjs.Current).ProjectItems));
                }
            }
            return result;
        }

        private static IEnumerable<string> GetsubItemImages(string root, string[] extensions, ProjectItems item)
        {
            var result = new List<string>();
            var enumprjs = item.GetEnumerator();
            while (enumprjs.MoveNext())
            {
                try
                {
                    var fileextension = ((ProjectItem)enumprjs.Current).Properties.Item("Extension").Value.ToString().ToUpper();
                    if (extensions.Any(extfind => fileextension.ToUpper() == extfind.ToUpper()))
                    {
                        var localpath = ((ProjectItem)enumprjs.Current).Properties.Item("LocalPath").Value.ToString();
                        result.Add(localpath.Replace(root, ""));
                    }
                }
                // ReSharper disable EmptyGeneralCatchClause
                catch
                // ReSharper restore EmptyGeneralCatchClause
                {
                }
                if (((ProjectItem)enumprjs.Current).ProjectItems != null)
                {
                    result.AddRange(GetsubItemImages(root, extensions, ((ProjectItem)enumprjs.Current).ProjectItems));
                }
            }
            return result.ToArray();
        }
    }
}